#include "Graphics3D.h"

//=====(PRIVATE) - EXTERNAL DATA READING
void Graphics3D::LoadTexture(IDirect3DDevice9* Device,int Element, string Address)
{
	D3DXCreateTextureFromFileEx										
		(Device, Address.c_str(), 0, 0, 0, 0,
		D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT,
		D3DX_DEFAULT, D3DCOLOR_XRGB(0, 0 ,255),
		&mdImageInfo[Element], 0, &mdTextures[Element]);

	D3DSURFACE_DESC Dimensions;
	mdTextures[Element]->GetLevelDesc(0,&Dimensions);
	float X = Dimensions.Width  * 0.5f;
	float Y = Dimensions.Height * 0.5f;
	mdTexCenter[Element] = D3DXVECTOR3(X,Y,0.0f);
}
void Graphics3D::LoadMeshFile(IDirect3DDevice9* Device,const char* cszXFile, ID3DXMesh*& pMesh)
{
	//=====VARIABLES
	ID3DXBuffer* pAdjacency = NULL;			// required for OptimizeInPlace
	ID3DXBuffer* pMaterials = NULL;			// materials for each subset
	ID3DXBuffer* pEffectsInstances = NULL;	// not interested in effects now
	ID3DXMesh* pClone = NULL;
	DWORD dMeshFVF	= NULL;
	DWORD dError	= NULL;
	DWORD dwNumMaterials = 0;


	if (NULL != pMesh)	pMesh->Release();		//Empty mesh
	pMesh = NULL;

	HR(D3DXLoadMeshFromX(cszXFile, D3DXMESH_MANAGED,			//Load file into mesh
		Device, &pAdjacency, &pMaterials,						//-Load file into mesh
		&pEffectsInstances, &dwNumMaterials, &pMesh));			//-Load file into mesh
	dError = ::GetLastError();									//Check Error
	dMeshFVF = pMesh->GetFVF();									//Get the Flexible Format 
	HR(pMesh->CloneMeshFVF(D3DPOOL_MANAGED, D3DFVF_XYZ			//Clone the mesh, ensure room for
		| D3DFVF_NORMAL | D3DFVF_TEX2, Device, &pClone));		//position, normals and textures
	pMesh->Release();											//Release the mesh
	pMesh = pClone;												//Set the mesh to the clone
	if (0 == (dMeshFVF & D3DFVF_NORMAL))						//Recompute normals	if not in the file
		HR(D3DXComputeNormals(pMesh,							//-Recompute normals if not in the file
		(DWORD*)pAdjacency->GetBufferPointer()));				//-Recompute normals if not in the file
	HR(pMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT				//Optimise mesh
		| D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE,		//-Optimise mesh
		(DWORD*)pAdjacency->GetBufferPointer(),					//-Optimise mesh
		0, 0, 0));												//-Optimise mesh
	pAdjacency->Release();			//Empty Buffer
	pEffectsInstances->Release();	//Empty Buffer
	pMaterials->Release();			//Empty Buffer
}
//=====INITIALIZE
void Graphics3D::Initialize	(IDirect3DDevice9* Device)
{
	InitTextures(Device);
	if(!InitMeshes(Device))
		::MessageBoxA(NULL, "Meshes not loaded", "InitMeshes()", MB_OK);
	ZeroMemory(&m_dmDefaultMaterial, sizeof(D3DMATERIAL9));
	m_dmDefaultMaterial.Ambient = D3DXCOLOR(0.5f, 0.5f, 0.2f, 0.2f);

	m_dmDefaultMaterial.Diffuse = D3DXCOLOR(0.1f, 0.1f, 0.0f, 1.0f);
	m_dmDefaultMaterial.Specular = D3DXCOLOR(0.2f, 0.2f, 0.0f, 1.0f);
	m_dmDefaultMaterial.Power = 2;


	ZeroMemory(&m_dmHighLightMaterial, sizeof(D3DMATERIAL9));
	m_dmDefaultMaterial.Ambient = D3DXCOLOR(0.5f, 0.5f, 0.2f, 0.2f);

	m_dmDefaultMaterial.Diffuse = D3DXCOLOR(0.1f, 0.1f, 0.0f, 1.0f);
	m_dmDefaultMaterial.Specular = D3DXCOLOR(0.2f, 0.2f, 0.0f, 1.0f);
	m_dmDefaultMaterial.Power = 5;

	Device->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);

	D3DXMatrixPerspectiveFovLH(&mPerspMat, D3DXToRadian(65), 
		SCREEN_WIDTH / SCREEN_HEIGHT, 1.0f, 1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &mPerspMat);
}
bool Graphics3D::InitTextures(IDirect3DDevice9* Device)
{
	m_cszTexNames[Neutral]	= "Textures//Neutral.png";
	m_cszTexNames[Player1]	= "Textures//Player1.png";
	m_cszTexNames[Player2]	= "Textures//Player2.png";

	for(int i = 0; i < D3OBJ_SIZE; i++)
		if(m_cszTexNames[i] != NULL){
			LoadTexture(Device,i,m_cszTexNames[i]);
			if(mdTextures[i] == NULL)		// if any file was unable to be loaded, stop the program
				return false;
		}

		return true;
};
bool Graphics3D::InitMeshes	(IDirect3DDevice9* Device)
{
	m_cszMeshNames[D3OBJ_EMPTY]		= "Meshes//Chit.x";
	m_cszMeshNames[D3OBJ_BOUNDARY]	= "Meshes//cube.x";
	m_cszMeshNames[D3OBJ_CHIT]		= "Meshes//Chit.x";
	m_cszMeshNames[D3OBJ_ARROW]		= "Meshes//Arrow.x";
	m_cszMeshNames[D3OBJ_PYRAMID]	= "Meshes//Pyramid.x";
	m_cszMeshNames[D3OBJ_SCARAB]	= "Meshes//Scarab.x";
	m_cszMeshNames[D3OBJ_SPHINX]	= "Meshes//Sphinx.x";
	m_cszMeshNames[D3OBJ_ANUBIS]	= "Meshes//Anubis.x";
	m_cszMeshNames[D3OBJ_PHARAOH]	= "Meshes//Pharaoh.x";
	m_cszMeshNames[D3OBJ_LASER]		= "Meshes//Lazer.x";
	m_cszMeshNames[D3OBJ_SIZE]		= NULL;

	for(int i = 0; i < D3OBJ_SIZE; i++)
		if(m_cszMeshNames[i] != NULL){
			LoadMeshFile(Device,m_cszMeshNames[i], mdMeshes[i]);
			if(mdMeshes[i] == NULL)	//If a mesh cannot be loaded, quit
				return false;
		}
		return true;						// return true if everything went well
};
//=====RENDER
bool Graphics3D::Render(IDirect3DDevice9* Device,DrawList& drawlist)
{
	for(unsigned i = 0; i < drawlist.size(); ++i)
	{	
		if(drawlist[i]->isVisible())
		{
			D3DXMatrixRotationYawPitchRoll(&mWorldMat,drawlist[i]->GetRotation().x,drawlist[i]->GetRotation().y,drawlist[i]->GetRotation().z);
			
			D3DXMatrixScaling(&mScaleMat,0.5f,0.5f,0.5f);
			D3DXMatrixTranslation(&mTransMat, drawlist[i]->GetX(), drawlist[i]->GetY(), drawlist[i]->GetZ());
			
			D3DXMatrixMultiply(&mWorldMat, &mWorldMat, &mScaleMat);
			D3DXMatrixMultiply(&mWorldMat, &mWorldMat, &mTransMat);
			Device->SetTransform(D3DTS_WORLD, &mWorldMat);
			Device->SetMaterial(&m_dmDefaultMaterial);
			
			Device->SetTexture(0, mdTextures[drawlist[i]->GetOwner()]);
			Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
			mdMeshes[drawlist[i]->GetID()]->DrawSubset(drawlist[i]->GetSubset());					//NOTE: Not sure if needed
		}

	}
	return true;
}